import Chess from "./Chess";

const {ccclass, property} = cc._decorator;
const GRID_SIZE = 15;
const GRID_WIDTH = 50;
const CHESS_BLACK = 'black';
const CHESS_WHITE = 'white';
const GRID_INIT = [7, 7];


@ccclass
export default class Game extends cc.Component {

    @property(cc.Node)
    bgNode: cc.Node = null;

    @property(cc.Node)
    rootNode: cc.Node = null;
    @property(cc.Prefab)
    chessPrefab:cc.Prefab = null;
    // 已下棋的格子
    private chessMap:Map<number,Chess> = new Map();
    // 该谁下棋了(black | white)
    private _turn : String
    // 最后下的棋子(有 红点 标识)
    private _lastChess:Chess
    private turn(){
        this._turn = this._turn == CHESS_BLACK ? CHESS_WHITE : CHESS_BLACK;
    }
    private _panelSettle:cc.Node;


    onLoad () {
        this.init();
    }

    start () {
        // this.showAll();
        this._turn = CHESS_BLACK;
        this.drawChess(GRID_INIT[0],GRID_INIT[1]);
        this.turn();
    }

    // update (dt) {}

    init() {
        const node = new cc.Node();
        node.parent = this.bgNode;
        node.setAnchorPoint(cc.Vec2.ZERO);
        
        const graphics = node.addComponent(cc.Graphics);
        graphics.lineWidth = 3;
        graphics.strokeColor = cc.Color.RED;
        // 从下往上 画横线
        for (let col = 0; col < GRID_SIZE; col++) {
            graphics.moveTo(GRID_WIDTH / 2,col * GRID_WIDTH + GRID_WIDTH / 2 );
            graphics.lineTo(GRID_SIZE * GRID_WIDTH - GRID_WIDTH / 2,col * GRID_WIDTH + GRID_WIDTH / 2);
            graphics.stroke();
            
        }
        // 从左往右 画竖线
        for (let row = 0; row < GRID_SIZE; row++) {
            graphics.moveTo(row * GRID_WIDTH + GRID_WIDTH / 2,GRID_WIDTH / 2 );
            graphics.lineTo(row * GRID_WIDTH + GRID_WIDTH / 2 ,GRID_SIZE * GRID_WIDTH - GRID_WIDTH / 2);
            graphics.stroke();
            
        }
        this.rootNode.on(cc.Node.EventType.TOUCH_START,(event:cc.Event.EventTouch) =>{
            const pos = this.rootNode.convertToNodeSpaceAR(event.getLocation());
            const [col,row] = this.posToGrid(pos);
            const idx = this.gridToIdx(col,row);
            if (this.chessMap.has(idx)) {
                return
            }
            this.drawChess(col,row);
            this.checkWin(col,row);
            this.turn();

        })
        this.panelSettleInit();
    }

    // 检查输赢的时候格子有越界情况，在这里判断，返回一个不在正常范围内的索引 [0, 224(15 * 15 -1)]
    private gridToIdx(col:number,row:number):number{
        if (col < 0 || col >= GRID_SIZE || row < 0 || row >= GRID_SIZE) {
            return -1;
        }
        return col * GRID_SIZE + row;
    }

    private gridToPos(col:number,row:number):cc.Vec2{
        return cc.v2(row * GRID_WIDTH + GRID_WIDTH / 2,col * GRID_WIDTH + GRID_WIDTH / 2);
    }
    private posToGrid(pos:cc.Vec2):number[] {
        return [Math.floor(pos.y / GRID_WIDTH),Math.floor(pos.x / GRID_WIDTH)];;
    }

    //棋盘随机显示所有棋子
    private showAll(){
        for (let col = 0; col < GRID_SIZE; col++) {
            for (let row = 0; row < GRID_SIZE; row++) {
                const chess = cc.instantiate(this.chessPrefab);
                chess.parent = this.rootNode;
                chess.setPosition(this.gridToPos(col,row));
                
                const name = this.randRange(0,1) == 1 ? CHESS_BLACK : CHESS_WHITE;
                const chessComp = chess.getComponent(Chess);
                chessComp.init(name);
            }
        }
    }
    randRange(min: number, max: number) {
        return Math.round(Math.random() * (max - min) + min);
    }

    drawChess(col:number,row:number){
        const idx = this.gridToIdx(col,row);
        const chess = cc.instantiate(this.chessPrefab);
        chess.parent = this.rootNode;
        chess.setPosition(this.gridToPos(col,row));
        if (this._lastChess) {
            this._lastChess.redHide();
        }
        const chessComp = chess.getComponent(Chess);;
        chessComp.init(this._turn);
        chessComp.redShow();

        this.chessMap.set(idx,chessComp);
        this._lastChess = chessComp;
    }

    private panelSettleInit(){
        this._panelSettle = this.node.getChildByName("panelSettle");
        this._panelSettle.active = false;
    }

    private panelSettleShow(msg:string){
        this._panelSettle.getChildByName("lblMsg").getComponent(cc.Label).string = msg;
        this._panelSettle.getChildByName('btnOk').on('click',() => cc.game.restart());

        this._panelSettle.active = true;
    }

    checkWin(col:number,row:number){
        let datas:Chess[] = [];
        // 左至右
        for (let i = row - 4; i <= row +4; i++) {
            datas.push(this.chessMap.get(this.gridToIdx(col,i)));            
        }
        if (this.checkWin2(datas)) {
            return
        }
        // 上至下
        datas = [];
        for (let i = col - 4; i <= col + 4; i++) {
           datas.push(this.chessMap.get(this.gridToIdx(i,row)));
        }
        if (this.checkWin2(datas)) {
            return
        }
        //左下到右上
        datas = [];
        for (let i = -4; i <= 4; i++) {
            datas.push(this.chessMap.get(this.gridToIdx(col + i,row + i)));            
        }
        if (this.checkWin2(datas)) {
            return
        }
        //左上到右下
        datas = [];
        for (let i = -4; i <= 4; i++) {
            datas.push(this.chessMap.get(this.gridToIdx(col - i,row + i)));
        }
        if (this.checkWin2(datas)) {
            return
        }
        if (this.chessMap.size == GRID_SIZE * GRID_SIZE) {
            this.panelSettleShow("平局");
        }
    }
    checkWin2(datas: Chess[]) {
        for (let i = 0; i < datas.length - 4; i++) {
            // 判断是否等于当前下的棋子
            if (datas[i]?.chessName != this._turn) {
                continue
            }
            // 到这里就是有一颗棋子了
            let sameNum = 1;
            for (let j = 0; j < datas.length; j++) {
                if (datas[j]?.chessName != this._turn) {
                    break
                }
                sameNum++;
                if (sameNum>=5) {
                    const msg = this._turn == CHESS_BLACK ? '黑棋赢了' : '白棋赢了';
                    this.panelSettleShow(msg);
                    return true;
                }
            }
        }
        return false;
    }
}
